package hao.itheima.aop;


import hao.itheima.mapper.OperateLogMapper;
import hao.itheima.pojo.OperateLog;
import hao.itheima.utils.CurrentHolder;
import hao.itheima.utils.JwtUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;

@Slf4j
//@Aspect // 声明切面类
@Component // 交给IOC容器进行管理
public class LogAspect {

    @Autowired
    private OperateLogMapper operateLogMapper;
    @Autowired
    private HttpServletRequest request;

    @Around("@annotation(hao.itheima.annotation.Log)") // 切入表达式,使用注解进行书写
    public Object record(ProceedingJoinPoint joinPoint) throws Throwable {
        //1.构造日志记录数据
        OperateLog operateLog = new OperateLog();
        //2.操作人--登录人id--在登录成功的时候将id存入到令牌中, 所以可以解析令牌获取登录id
        // 这里不需要进行异常处理, 因为拦截器与过滤器已经有对应的异常处理了
        //-----------------------------------------------
        //方式一:
//        String token = request.getHeader("Token");
//        Claims claims = JwtUtils.parseJWT(token);
//        Object empId = claims.get("id");
//        operateLog.setOperateEmpId((Integer) empId); // 知道它原本就是一个Integer类型, 可以直接进行强转

        //方式二: 使用TheadLocal 变量进行存储Token中的id
        // 存储的逻辑在过滤器当中
        operateLog.setOperateEmpId(getCurrentId()); // 知道它原本就是一个Integer类型, 可以直接进行强转


        //3.操作时间
        operateLog.setOperateTime(LocalDateTime.now());
        //4.执行方法全类名
        operateLog.setClassName(joinPoint.getTarget().getClass().getName());
        //5.执行方法名
        operateLog.setMethodName(joinPoint.getSignature().getName());
        //6.方法运行参数
        operateLog.setMethodParams(Arrays.toString(joinPoint.getArgs()));

        //7.返回值
        long begin = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        operateLog.setReturnValue(result != null ? result.toString() : "void");
        //8.方法执行耗时
        long end = System.currentTimeMillis();
        operateLog.setCostTime(end - begin);

        //9.存入日志表
        operateLogMapper.insert(operateLog);


        return result;
    }

    private Integer getCurrentId() {
        return CurrentHolder.getCurrentId();
    }
}
